import { _decorator, ERaycast2DType, PhysicsSystem2D, RigidBody2D, Vec2 } from 'cc';
import DataManager from '../Runtime/DataManager';
import { DIRECTION_ENUM, CHARGING_NAME_ENUM, GAME_MODE_ENUM } from '../../Enums';
import { BaseEnemy } from './BaseEnemy';
const { ccclass } = _decorator;
// 骷髅怪物
@ccclass('ChargingEnemy')
export class ChargingEnemy extends BaseEnemy {
    play_node
    playManager
    userNode
    speed: number = 4
    _status: string = ""
    initialize: Boolean = false
    positionX: number = 4
    positionY: number = 14
    _running: Boolean = false //是否冲刺状态
    pre_status: string  //上一个动画状态
    get running() {
        return this._running
    }
    set running(value: Boolean) {
        this._running = value
        if (this.running) {
            this.speed = 8
        } else {
            this.speed = 4
        }
    }
    async init(list) {
        super.initialization(
            "ChargingEnemy",
            this.positionX,
            this.positionY,
            this.positionX,
            20,
            CHARGING_NAME_ENUM,
            list
        )
    }
    // 获取怪物的状态信息
    getSendData() {
        if (this.node && this.node.isValid) {
            let { targetX, targetY, direction, state } = this.playManager
            return {
                name: this.node.name,
                x: Math.round(this.node.getPosition().x / this.speed) * this.speed,// 位置
                y: Math.round(this.node.getPosition().y / this.speed) * this.speed,
                direction,
                state,
                lineList:[],
                fly: false,
                avoid: false,
                running: this.running,
                status: this.status,
                dizzy: this.dizzy,
                speed: this.speed,
                dizzy_direction: this.dizzy_direction,
                callback: this.callback,
                callback_A: this.callback_A,
                callbackAvoid: this.callbackAvoid,
                targetX,
                targetY
            }
        }
    }
    // 强制设置角色的状态
    setSendData(data) {
        if (!data) return
        if (this.node && this.node.isValid) {
            if (!data?.x || !data?.y) return
            this.node.setPosition(data.x, data.y)
            this.playManager.targetX = data.targetX
            this.playManager.targetY = data.targetY
            this.playManager.direction = data.direction
            this.dizzy = data.dizzy
            this.running = data.running
            this.dizzy_direction = data.dizzy_direction
            this.status = data.status
            this.speed = data.speed
            clearTimeout(this.callback)
            clearTimeout(this.callback_A)
            if (this.playManager.state != data.state) {
                this.playManager.state = data.state
            }
        }
    }
    // 判断前方有没有角色,如果和角色之间没有障碍物并且间隔了四个格子,就冲刺;
    // 设置冲刺状态
    createdSprint() {
        if (!this.running) {
            let { targetX, targetY } = this.walkingLogic(this.status)
            this.playManager.targetX = targetX
            this.playManager.targetY = targetY
            let { direction } = this.playManager
            if (direction == DIRECTION_ENUM.TOP) {
                this.playManager.state = CHARGING_NAME_ENUM.TOPRUN
            } else if (direction == DIRECTION_ENUM.LEFT) {
                this.playManager.state = CHARGING_NAME_ENUM.LEFTRUN
            } else if (direction == DIRECTION_ENUM.BOTTOM) {
                this.playManager.state = CHARGING_NAME_ENUM.BOTTOMRUN
            } else if (direction == DIRECTION_ENUM.RIGHT) {
                this.playManager.state = CHARGING_NAME_ENUM.RIGHTRUN
            }
            this.speed = 8
            this.running = true
        }
    }
    // 判断正前方有没有障碍物
    physicsStraightLine() {
        if (this.running) return
        let { direction } = this.playManager
        let { width, position, mapWidth, mapHeight, height } = DataManager.Instance
        let start = new Vec2(this.node.getWorldPosition().x, this.node.getWorldPosition().y)
        let endX = this.node.getWorldPosition().x
        let endY = this.node.getWorldPosition().y
        if (direction == DIRECTION_ENUM.TOP) {
            endY = mapHeight
        } else if (direction == DIRECTION_ENUM.BOTTOM) {
            endY = -mapHeight / 2
        } else if (direction == DIRECTION_ENUM.LEFT) {
            endX = 0
        } else if (direction == DIRECTION_ENUM.RIGHT) {
            endX = mapWidth
        }
        let result = PhysicsSystem2D.instance.raycast(start, new Vec2(endX, endY), ERaycast2DType.All);

        let filterName = ['enemy', 'sensor', 'children_lurker', 'slide']
        let list = result.filter((item => !filterName.find(item1 => item.collider.node.name.includes(item1))))
        if (list.length > 0) {
            let arr = this.coordinateComparison(list)
            let { x, y } = this.node.getPosition()
            if (!arr[0].collider.node.name.includes("role")) return
            let detail = list.length == 1 ? arr[0].collider.node : arr[1].collider.node
            let { x: node_x, y: node_y } = detail.getPosition()
            let powerX = 0, distanceX, powerY = 0, distanceY
            if (direction == DIRECTION_ENUM.TOP) {
                distanceY = Math.round(y - node_y)
                powerY = Math.floor(distanceY / position) + 2
                if (powerY <= -4) {
                    this.playManager.end_w = node_y - height + ((height - position) / 2)
                    this.createdSprint()
                }
            } else if (direction == DIRECTION_ENUM.BOTTOM) {
                distanceY = Math.round(node_y - y)
                powerY = Math.floor(distanceY / position)
                if (powerY <= -4) {
                    this.playManager.end_s = node_y + height - position + 4  //+4是因为角色下一格是障碍物的话，会导致怪物位置和目标位置差4永远到不了
                    this.createdSprint()
                }
            } else if (direction == DIRECTION_ENUM.LEFT) {
                distanceX = Math.round(x - node_x)
                powerX = Math.round(distanceX / width)
                if (powerX >= 4) {
                    this.playManager.end_a = Math.round(node_x + width)
                    this.createdSprint()
                }
            } else if (direction == DIRECTION_ENUM.RIGHT) {
                distanceX = Math.round(node_x - x)
                powerX = Math.floor(distanceX / width)
                if (powerX >= 4) {
                    this.playManager.end_d = Math.ceil(node_x - width)
                    this.createdSprint()
                }
            }
        }
    }
    update() {
        if (DataManager.Instance.gameMode == GAME_MODE_ENUM.ONLINE) {
            if (!DataManager.Instance.game_ready) return
            if (DataManager.Instance.ping_time >= 460) {
                let rb = this.node.getComponent(RigidBody2D)
                rb!.linearVelocity = new Vec2(0, 0)
                return
            }
        }
        if (this.dizzy) {
            this.dizzy_update()
        } else {
            this.enemy_update()
        }
    }
    enemy_update() {
        if (this.dizzy) return
        let rb = this.node.getComponent(RigidBody2D)
        let speed = this.speed
        let lv = rb!.linearVelocity;
        let { x, y } = this.node.getPosition()
        y = Math.round(y / 4) * 4
        x = Math.round(x / 4) * 4
        if (this.status == "KEY_A") {
            lv.x = -speed;
            lv = new Vec2(lv.x, 0);
        } else if (this.status == "KEY_D") {
            lv.x = speed;
            lv = new Vec2(lv.x, 0);
        } else if (this.status == "KEY_W") {
            lv.y = +speed;
            lv = new Vec2(0, lv.y);
        } else if (this.status == "KEY_S") {
            lv.y = -speed;
            lv = new Vec2(0, lv.y);
        } else {
            lv = new Vec2(0, 0);
        }
        let { targetX, targetY, direction } = this.playManager
        if (direction == DIRECTION_ENUM.LEFT || direction == DIRECTION_ENUM.RIGHT) {
            if (targetX != 0) {
                if (x > parseInt(targetX + '')) {
                    lv.x = -speed;
                    lv = new Vec2(lv.x, 0);
                    this.playManager.disabled = true
                } else if (x < parseInt(targetX + '')) {
                    lv.x = +speed;
                    lv = new Vec2(lv.x, 0);
                    this.playManager.disabled = true
                } else {
                    this.node.setPosition(targetX, y)
                    this.resetPlayManager()
                    if (this.running) {
                        this.running = false
                    }
                    this.physicsStraightLine()
                    this.pre_status = this.status
                    this.status = ""
                    lv = new Vec2(0, 0);
                }
            }
        }
        if (direction == DIRECTION_ENUM.TOP || direction == DIRECTION_ENUM.BOTTOM) {
            if (targetY != 0) {
                if (y < parseInt(targetY + '')) {
                    lv.y = +speed;
                    lv = new Vec2(0, lv.y);
                    this.playManager.disabled = true
                } else if (y > parseInt(targetY + '')) {
                    lv.y = -speed;
                    lv = new Vec2(0, lv.y);
                    this.playManager.disabled = true
                } else {
                    this.node.setPosition(x, targetY)
                    this.resetPlayManager()
                    if (this.running) {
                        this.running = false
                    }
                    this.physicsStraightLine()
                    this.pre_status = this.status
                    this.status = ""
                    lv = new Vec2(0, 0);

                }
            }
        }
        rb!.linearVelocity = lv;
        if (this.initialize) {
            if (!this.running) {
                this.physicsTestAABB()
            }
        }
    }
    resetPlayManager() {
        this.playManager.targetX = 0
        this.playManager.targetY = 0
        this.playManager.end_w = 0
        this.playManager.end_a = 0
        this.playManager.end_s = 0
        this.playManager.end_d = 0
        this.playManager.disabled = false
    }
}


